// COMPILES: g++ -o tutorial constructora.cpp -export-dynamic `pkg-config --cflags --libs gtk+-2.0`
// Debe existir el archivo gui.xml que define la interfaz
// (hacerla con glade3, y convertir con "gtk-builder-convert gui.glade gui.xml")

#include <gtk/gtk.h>
#include <iostream>
#include <string>
#include <sstream>
#include "../constructora.h"

typedef struct{
	GtkWidget*	window;
	GtkWidget*	ag_viv;
	GtkWidget*	monitor;
	
	GtkSpinButton* agviv_mat;
	GtkSpinButton* agviv_cant;
	GtkTextView*	agviv_text;
	GtkLabel*		label_viv;
	
	GtkButton*		but_ag_viv;
	GtkListStore*	viv_list;
	GtkButton*		but_crear;
	
	GtkVBox*			box_constr;
	GtkSpinButton*	spin_comprar_mat;
	GtkSpinButton*	spin_comprar_cant;
	GtkSpinButton*	spin_construir;
	
	GtkListStore*	list_stock;
	GtkListStore*	list_pend;
	GtkListStore*	list_deuda;
	
	GtkStatusbar*	statusbar;

	Multiconj_materiales* mm;
	Catalogo cat;
	constructora* C;
	
	void setStatus(string str){
		gtk_statusbar_push(statusbar,0,str.c_str());
		//std::cout << str << std::endl;
	}
} Gui;


string int2str(int val){
	return g_strdup_printf("%d", val);
}
int spinVal(GtkSpinButton* spin){
	return gtk_spin_button_get_value_as_int(spin);
}
void setText(GtkTextView* tv, string str){
	gtk_text_buffer_set_text( gtk_text_view_get_buffer(tv),str.c_str(),-1);
}
void refresh(Gui* gui){
	GtkTreeIter iter;
	for(int i=0;i<gui->C->stock().cantMateriales();i++){
		GtkTreePath* path = gtk_tree_path_new_from_string(int2str(i).c_str());
		gtk_tree_model_get_iter(GTK_TREE_MODEL(gui->list_stock),&iter,path);
		gtk_tree_path_free(path);
		gtk_list_store_set(gui->list_stock,&iter,1,gui->C->stock().cardinal(i),-1);
	}
	
	gtk_list_store_clear(gui->list_pend);
	Lista<vivienda> cola = gui->C->pendientes().cola();
	Lista<vivienda>::IterLista_const itpend=cola.crearIt_const();
	while(itpend.tieneProximo()){
		gtk_list_store_append(gui->list_pend, &iter);  /* Acquire an iterator */
		gtk_list_store_set(gui->list_pend,&iter, 0,itpend.actual(),-1);
		itpend.avanzar();
	}
	
	gtk_list_store_clear(gui->list_deuda);
	Multiconj_materiales deuda = gui->C->deuda();
	Multiconj_materiales::IterMateriales itdeuda=deuda.crearIterMateriales();
	while(itdeuda.tieneProximo()){
		gtk_list_store_append(gui->list_deuda, &iter);
		material actual=itdeuda.avanzar();
		gtk_list_store_set(gui->list_deuda,&iter, 0,actual, 1,gui->C->deuda().cardinal(actual),-1);
	}
}
void makeStock(Gui* gui){
	GtkTreeIter iter;
	for(int i=0;i<gui->C->stock().cantMateriales();i++){
		gtk_list_store_append(gui->list_stock, &iter);  /* Acquire an iterator */
		gtk_list_store_set(gui->list_stock,&iter, 0,i, 1,0,-1);
	}
}

extern "C" void on_but_ag_viv_clicked(GtkButton *button, Gui* gui){
   gtk_widget_show(gui->ag_viv);
   gtk_text_buffer_set_text( gtk_text_view_get_buffer(gui->agviv_text),"",-1);
   gtk_spin_button_set_value(gui->agviv_mat,0);
   gtk_spin_button_set_value(gui->agviv_cant,1);
   gui->mm = new Multiconj_materiales();
}

extern "C" void on_ag_mat_clicked(GtkButton *button, Gui* gui){
	gui->mm->agregar(gtk_spin_button_get_value_as_int(gui->agviv_mat), gtk_spin_button_get_value_as_int(gui->agviv_cant));
	Multiconj_materiales::IterMateriales it = gui->mm->crearIterMateriales();
	string str="";
	while(it.tieneProximo()){
		material m=it.avanzar();
		str += g_strdup_printf("%dx Material %d\n", gui->mm->cardinal(m), m);
	}
   //gtk_text_buffer_set_text( gtk_text_view_get_buffer(gui->agviv_text),g_strdup_printf("%d", gui->mm->cardinal(4)),-1);
   gtk_text_buffer_set_text( gtk_text_view_get_buffer(gui->agviv_text),str.c_str(),-1);
}

extern "C" bool on_ag_viv_destroy(GtkWidget* agviv, Gui* gui){
	delete gui->mm;
	gtk_widget_hide(agviv);
	return true;
}

extern "C" void on_cancel_agviv(GtkButton* button, Gui* gui){
	on_ag_viv_destroy(gui->ag_viv, gui);
}

extern "C" void agviv_apply(GtkButton* button, Gui* gui){
	if(!gui->mm->vacio()){
		gui->cat.agregarVivienda(*gui->mm);
		/*string label="Cantidad de Viviendas: ";
		label += g_strdup_printf("%d", gui->cat.cantidadViviendas());
		gtk_label_set_text(gui->label_viv,label.c_str());*/
		//std::cout << gui->cat.cantMateriales() << std::endl;
	
		GtkTreeIter iter;
		gtk_list_store_append(gui->viv_list, &iter);  /* Acquire an iterator */
		/*ostringstream out;
		gui->mm->mostrarMulticonj_materiales(out);*/
		string str;
		Multiconj_materiales::IterMateriales it = gui->mm->crearIterMateriales();
		while(it.tieneProximo()){
			material mat=it.avanzar();
			str+=int2str(gui->mm->cardinal(mat))+"x <b>"+int2str(mat)+"</b>, ";
		}
		gtk_list_store_set(gui->viv_list,&iter, 0,gui->cat.cantidadViviendas()-1, 1,str.c_str(),-1);
		
		on_ag_viv_destroy(gui->ag_viv, gui);
	}
}

extern "C" void crear_constr(GtkButton* button, Gui* gui){
	if(gui->cat.cantidadViviendas()>0){
		gtk_widget_set_sensitive(GTK_WIDGET(gui->but_ag_viv),false);
		gtk_widget_hide(GTK_WIDGET(button));
		gtk_widget_show(GTK_WIDGET(gui->box_constr));
	
		gtk_spin_button_set_range(gui->spin_comprar_mat,0,gui->cat.cantMateriales());
		gtk_spin_button_set_value(gui->spin_comprar_cant,1);
		gtk_spin_button_set_range(gui->spin_construir,0,gui->cat.cantidadViviendas()-1);
	
		gui->C = new constructora(gui->cat);
		makeStock(gui);
	}
}

extern "C" void comprar(GtkButton* button, Gui* gui){
	gui->C->comprar(spinVal(gui->spin_comprar_mat),spinVal(gui->spin_comprar_cant));
	refresh(gui);
	string txt="Se compraron "+int2str(spinVal(gui->spin_comprar_cant))+" unidades del material "+int2str(spinVal(gui->spin_comprar_mat));
	//setText(gui->status, txt);
	gui->setStatus(txt);
}

extern "C" void construir(GtkButton* button, Gui* gui){
	gui->C->construir(spinVal(gui->spin_construir));
	refresh(gui);
	string txt="se mando a construir la vivienda "+int2str(spinVal(gui->spin_construir));
	//setText(gui->status, txt);
	gui->setStatus(txt);
}

extern "C" void donar(GtkButton* button, Gui* gui){
	string txt="Se donaron "+int2str(gui->C->stock().cardinal(gui->C->stock().elQueMasHay())/5)+" unidades del material "+int2str(gui->C->stock().elQueMasHay());
	gui->C->donar();
	refresh(gui);
	//setText(gui->status, txt);
	gui->setStatus(txt);
}

extern "C" void ver(GtkButton* button, Gui* gui){
	gtk_widget_show(gui->monitor);
	gtk_widget_grab_focus(gui->monitor);

	/*ostringstream out;
	gui->C->pendientes().cola().mostrarLista(out);
	gui->C->deuda().mostrarMulticonj_materiales(out);*/
	//setText(gui->status, "Deuda:\n"+out.str());
}

extern "C" bool monitor_close(GtkWidget* win, Gui* gui){
	gtk_widget_hide(win);
	return true;
}
 
int main (int argc, char *argv[]){
	Gui* gui;

	/* allocate the memory needed by our Gui struct */
	gui = g_slice_new(Gui);

	gtk_init(&argc, &argv);
	
	GtkBuilder* builder;
	builder = gtk_builder_new();
	gtk_builder_add_from_file(builder, "gui.xml", NULL);

	gui->window = GTK_WIDGET(gtk_builder_get_object(builder, "constr"));
	gui->ag_viv = GTK_WIDGET(gtk_builder_get_object(builder, "ag_viv"));
	gui->monitor = GTK_WIDGET(gtk_builder_get_object(builder, "monitor"));
	
	gui->agviv_mat = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "agviv_spin_mat"));
	gui->agviv_cant = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "agviv_spin_cant"));
	gui->agviv_text = GTK_TEXT_VIEW(gtk_builder_get_object(builder, "multiconj"));
	gui->label_viv = GTK_LABEL(gtk_builder_get_object(builder, "label_cant_viv"));
	
	gui->but_ag_viv = GTK_BUTTON(gtk_builder_get_object(builder, "but_ag_viv"));
	gui->but_crear = GTK_BUTTON(gtk_builder_get_object(builder, "crear"));
	
	gui->box_constr = GTK_VBOX(gtk_builder_get_object(builder, "box_constr"));
	gui->spin_comprar_mat = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_comprar_mat"));
	gui->spin_comprar_cant = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_comprar_cant"));
	gui->spin_construir = GTK_SPIN_BUTTON(gtk_builder_get_object(builder, "spin_constviv"));
	//gui->viv_list = GTK_WIDGET( gtk_builder_get_object( builder, "tree_viviendas" ) );
	gui->viv_list = GTK_LIST_STORE( gtk_builder_get_object( builder, "list_viviendas"));
	
	gui->list_stock = GTK_LIST_STORE( gtk_builder_get_object( builder, "list_stock"));
	gui->list_pend = GTK_LIST_STORE( gtk_builder_get_object( builder, "list_pend"));
	gui->list_deuda = GTK_LIST_STORE( gtk_builder_get_object( builder, "list_deuda"));
	
	gui->statusbar = GTK_STATUSBAR( gtk_builder_get_object( builder, "statusbar"));

	gtk_builder_connect_signals(builder, gui);
	g_object_unref(G_OBJECT(builder));

	gtk_widget_show(gui->window);
	gtk_main();
	
	/* free memory we allocated for Gui struct */
	g_slice_free(Gui, gui);

	return 0;
}
